home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume8 / se / part02 < prev    next >
Encoding:
Internet Message Format  |  1987-01-25  |  53.0 KB

  1. Subject:  v08i002:  Georgia Tech 'se' Screen Editor
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: emoryu1!arnold (Arnold D. Robbins)
  6. Mod.sources: Volume 8, Issue 2
  7. Archive-name: se/Part02
  8.  
  9.  
  10. Here is the second release of the Georgia Tech Screen Editor, 'se'.
  11. There were enough changes that a whole new posting is warranted.
  12.  
  13. Major Changes:
  14.     All Georgia Tech specific stuff removed.
  15.     It understands window size changes on 4.3BSD and ATT Unix PC/3B1
  16.     Support for the shared library on the ATT Unix PC/3B1
  17.     Considerable source code reorganization in certain files.
  18.  
  19. Enjoy,
  20.  
  21. Arnold Robbins
  22.  
  23. #! /bin/sh
  24. # This is a shell archive, meaning:
  25. # 1. Remove everything above the #! /bin/sh line.
  26. # 2. Save the resulting text in a file.
  27. # 3. Execute the file with /bin/sh (not csh) to create the files:
  28. #    edit.c
  29. #    extern.h
  30. #    m4munge
  31. #    main.c
  32. #    makefile
  33. #    misc.c
  34. export PATH; PATH=/bin:$PATH
  35. echo shar: extracting "'edit.c'" '(26346 characters)'
  36. if test -f 'edit.c'
  37. then
  38.     echo shar: will not over-write existing file "'edit.c'"
  39. else
  40. cat << \SHAR_EOF > 'edit.c'
  41. #ifndef lint
  42. static char RCSid[] = "$Header: edit.c,v 1.3 86/07/11 15:11:34 osadr Exp $";
  43. #endif
  44.  
  45. /*
  46.  * $Log:    edit.c,v $
  47.  * Revision 1.3  86/07/11  15:11:34  osadr
  48.  * Removed Georgia Tech specific code.
  49.  * 
  50.  * Revision 1.2  86/05/27  17:44:56  osadr
  51.  * Removed flexnames dependancy; PREVLINE[2] --> PREVLN[2].
  52.  * Improved the sysname() routine, particularly to use the nodename
  53.  * member of the utsname structure under System V.
  54.  * 
  55.  * Revision 1.1  86/05/06  13:37:16  osadr
  56.  * Initial revision
  57.  * 
  58.  * 
  59.  */
  60.  
  61. /*
  62. ** edit.c
  63. **
  64. ** editor main routine, plus other routines used a lot.
  65. */
  66.  
  67. #include "se.h"
  68. #include "extern.h"
  69.  
  70. static char Savknm = DEFAULTNAME;    /* saved mark name for < and > */
  71.  
  72. /* edit --- main routine for screen editor */
  73.  
  74. edit (argc, argv)
  75. int argc;
  76. char *argv[];
  77. {
  78.     int cursav, status, len, cursor;
  79.     int ckglob (), docmd (), doglob (), doread ();
  80.     int getlst (), nextln (), prevln ();
  81.     char lin[MAXLINE], term;
  82.  
  83.     watch ();       /* display time of day */
  84.  
  85. #ifdef LOG_USAGE
  86.     log ();        /* log who used the program */
  87. #endif
  88.  
  89.     serc ();    /* execute commands in ./.serc or $HOME/.serc */
  90.  
  91.     status = OK;
  92.  
  93.     while (status == OK && Argno < argc)
  94.     {
  95.         strcpy (lin, argv[Argno]);
  96.         loadstr (lin, Argno, POOPCOL, Ncols);
  97.         if (lin[0] == '-')
  98.         {
  99.             len = strlen (lin) + 1;
  100.             lin[len - 1] = '\n';
  101.             lin[len] = EOS;
  102.             len = 0;
  103.             status = doopt (lin, &len);
  104.         }
  105.         else
  106.         {
  107.             dfltsopt (lin);
  108.             status = doread (Lastln, lin, NO);
  109.         }
  110.         Argno++;
  111.     }
  112.  
  113.     if (status == ERR)
  114.     {
  115.         if (Errcode == EHANGUP)
  116.             hangup ();
  117.         printverboseerrormessage ();
  118.     }
  119.     else
  120.         Curln = min (1, Lastln);
  121.  
  122.     Buffer_changed = NO;
  123.     First_affected = 1;     /* maintained by updscreen & commands */
  124.     updscreen ();
  125.  
  126.     if (status != ERR)    /* leave offending file name or option */
  127.         lin[0] = EOS;
  128.     cursor = 0;
  129.  
  130.     /* main command loop */
  131.     do {
  132.         intrpt ();    /* discard pending breaks (interrupts) */
  133.         if (Lost_lines > GARB_THRESHOLD
  134.             && (Lastln + Limcnt) / Lost_lines <= GARB_FACTOR)
  135.             garbage_collect ();
  136.  
  137.         mswait ();    /* check for pending messages */
  138.         Cmdrow = Botrow + 1;    /* reset the command line location */
  139.         prompt ("cmd>");
  140.         getcmd (lin, 0, &cursor, &term);
  141.         remark ("");    /* clear out any error messages */
  142.  
  143.         while (term == CURSOR_UP || term == CURSOR_DOWN
  144.             || term == CURSOR_SAME)
  145.         {
  146.             switch (term) {
  147.             case CURSOR_UP:
  148.                 if (Curln > 1)
  149.                     Curln--;
  150.                 else
  151.                     Curln = Lastln;
  152.                 break;
  153.  
  154.             case CURSOR_DOWN:
  155.                 if (Curln < Lastln)
  156.                     Curln++;
  157.                 else
  158.                     Curln = min (1, Lastln);
  159.                 break;
  160.             }
  161.             adjust_window (Curln, Curln);
  162.             updscreen ();
  163.             getcmd (lin, 0, &cursor, &term);
  164.         }
  165.  
  166.         prompt ("");    /* remove prompt */
  167.  
  168.         cursav = Curln;        /* remember it in case of an error */
  169.         Errcode = EEGARB;    /* default error code for garbage at end */
  170.  
  171.         len = 0;
  172.         if (getlst (lin, &len, &status) == OK)
  173.         {
  174.             if (ckglob (lin, &len, &status) == OK)
  175.                 doglob (lin, &len, &cursav, &status);
  176.             else if (status != ERR)
  177.                 docmd (lin, len, NO, &status);
  178.         }
  179.         if (status == ERR)
  180.         {
  181.             if (Errcode == EHANGUP)
  182.                 hangup ();
  183.             printverboseerrormessage ();
  184.             Curln = min (cursav, Lastln);
  185.         }
  186.         else if (term != FUNNY)
  187.         {
  188.             cursor = 0;
  189.             lin[0] = EOS;
  190.         }
  191.  
  192.         adjust_window (Curln, Curln);
  193.         updscreen ();
  194.  
  195.     } while (status != EOF);
  196.  
  197.     clrscreen ();
  198.     clrbuf ();
  199.     tflush ();
  200.  
  201.     return;
  202. }
  203.  
  204.  
  205. /* getlst --- collect line numbers (if any) at lin[*i], increment i */
  206.  
  207. int getlst (lin, i, status)
  208. char lin[];
  209. int *i, *status;
  210. {
  211.     int num;
  212.     int getone ();
  213.  
  214.     Line2 = 0;
  215.     for (Nlines = 0; getone (lin, i, &num, status) == OK; )
  216.     {
  217.         Line1 = Line2;
  218.         Line2 = num;
  219.         Nlines++;
  220.         if (lin[*i] != ',' && lin[*i] != ';')
  221.             break;
  222.         if (lin[*i] == ';')
  223.             Curln = num;
  224.         (*i)++;
  225.     }
  226.  
  227.     if (Nlines > 2)
  228.         Nlines = 2;
  229.  
  230.     if (Nlines <= 1)
  231.         Line1 = Line2;
  232.  
  233.     if (Line1 > Line2)
  234.     {
  235.         *status = ERR;
  236.         Errcode = EBACKWARD;
  237.     }
  238.  
  239.     if (*status != ERR)
  240.         *status = OK;
  241.  
  242.     return (*status);
  243. }
  244.  
  245.  
  246. /* getnum --- convert one term to line number */
  247.  
  248. int getnum (lin, i, pnum, status)
  249. char lin[];
  250. register int *i, *pnum, *status;
  251. {
  252.     int j, ret;
  253.     int ctoi (), optpat (), ptscan (), knscan (), getkn ();
  254.     int k;
  255.  
  256.     ret = OK;
  257.     SKIPBL (lin, *i);
  258.     if (lin[*i] >= Rel_a && lin[*i] <= Rel_z && Absnos == NO)
  259.         *pnum = Topln - Toprow + lin[*i] - Rel_a;
  260.     else if (lin[*i] == CURLINE)
  261.         *pnum = Curln;
  262.     else if (lin[*i] == PREVLN || lin[*i] == PREVLN2)
  263.         *pnum = Curln - 1;
  264.     else if (lin[*i] == LASTLINE)
  265.         *pnum = Lastln;
  266.     else if (lin[*i] == SCAN || lin[*i] == BACKSCAN)
  267.     {
  268.         int missing_delim = YES;
  269.  
  270.         /* see if trailing delim supplied, since command can follow pattern */
  271.         for (k = *i + 1; lin[k] != EOS; k++)
  272.             if (lin[k] == ESCAPE)
  273.                 k++;    /* skip esc, loop will skip escaped char */
  274.             else if (lin[k] == lin[*i])
  275.             {
  276.                 missing_delim = NO;
  277.                 break;
  278.             }
  279.             /* else
  280.                 continue */
  281.         
  282.         if (missing_delim == YES)
  283.         {
  284.             for (; lin[k] != EOS; k++)
  285.                 ;
  286.             k--;        /* k now at newline */
  287.  
  288.             /* supply trailing delim */
  289.             lin[k] = lin[*i];
  290.             lin[++k] = '\n';
  291.             lin[++k] = EOS;
  292.             Peekc = SKIP_RIGHT;
  293.         }
  294.  
  295.         if (optpat (lin, i) == ERR)
  296.             ret = ERR;
  297.         else if (lin[*i] == SCAN)
  298.             ret = ptscan (FORWARD, pnum);
  299.         else 
  300.             ret = ptscan (BACKWARD, pnum);
  301.     }
  302.     else if (lin[*i] == SEARCH || lin[*i] == BACKSEARCH)
  303.     {
  304.         j = *i;
  305.         (*i)++;
  306.         if (getkn (lin, i, &Savknm, Savknm) == ERR)
  307.             ret = ERR;
  308.         else if (lin[j] == SEARCH)
  309.             ret = knscan (FORWARD, pnum);
  310.         else
  311.             ret = knscan (BACKWARD, pnum);
  312.         (*i)--;
  313.     }
  314.     else if (isdigit (lin[*i]))
  315.     {
  316.         *pnum = ctoi (lin, i);
  317.         (*i)--;
  318.     }
  319.     else if (lin[*i] == TOPLINE)
  320.         *pnum = Topln;
  321.     else
  322.         ret = EOF;
  323.  
  324.     if (ret == OK)
  325.         (*i)++;
  326.     *status = ret;
  327.     return (ret);
  328. }
  329.  
  330.  
  331. /* getone --- evaluate one line number expression */
  332.  
  333. int getone (lin, i, num, status)
  334. char lin[];
  335. register int *i, *num, *status;
  336. {
  337.     int pnum, ret;
  338.     int getnum ();
  339.     char porm;    /* "plus or minus" (sic) */
  340.  
  341.     ret = EOF;    /* assume we won't find anything for now */
  342.     *num = 0;
  343.  
  344.     if (getnum (lin, i, num, status) == OK)        /* first term */
  345.     {
  346.         ret = OK;    /* to indicate we've seen something */
  347.         do {            /* + or - terms */
  348.             porm = EOS;
  349.             SKIPBL (lin, *i);
  350.             if (lin[*i] == '-' || lin[*i] == '+')
  351.             {
  352.                 porm = lin[*i];
  353.                 (*i)++;
  354.             }
  355.             if (getnum (lin, i, &pnum, status) == OK)
  356.                 if (porm == '-')
  357.                     *num -= pnum;
  358.                 else
  359.                     *num += pnum;
  360.             if (*status == EOF && porm != EOS)    /* trailing + or - */
  361.                 *status = ERR;
  362.         } while (*status == OK);
  363.     }
  364.  
  365.     if (*num < 0 || *num > Lastln)    /* make sure number is in range */
  366.     {
  367.         *status = ERR;
  368.         Errcode = EORANGE;
  369.     }
  370.  
  371.     if (*status == ERR)
  372.         ret = ERR;
  373.     else
  374.         *status = ret;
  375.  
  376.     return (ret);
  377. }
  378.  
  379.  
  380. #ifndef OLD_SCRATCH
  381. #ifndef OLD_GLOB
  382. static int special_casing = NO;
  383. #endif
  384. #endif
  385.  
  386. /* ckglob --- if global prefix, mark lines to be affected */
  387.  
  388. int ckglob (lin, i, status)
  389. char lin[];
  390. int *i, *status;
  391. {
  392.     register int line, tmp;
  393.     int usepat, usemark;
  394.     int defalt (), match (), optpat (), getkn ();
  395.     register LINEDESC *k;
  396.     LINEDESC *gettxt (), *getind ();
  397.  
  398.     *status = OK;
  399.     usepat = EOF;
  400.     usemark = EOF;
  401.  
  402. #ifndef OLD_SCRATCH
  403. #ifndef OLD_GLOB
  404.     if (    /* g/^/m0  or g/$/m0 -- special case the pathological */
  405.         /* cases in order to save time */
  406.         (lin[*i] == GLOBAL || lin[*i] == UCGLOBAL)
  407.         && (lin[*i + 1] == lin[*i + 3])
  408.         && (lin[*i + 2] == '^' || lin[*i + 2] == '$')
  409.         && (lin[*i + 4] == MOVECOM || lin[*i + 4] == UCMOVECOM)
  410.         && (lin[*i + 5] == '0' && lin[*i + 6] == '\n')   )
  411.     {
  412.         special_casing = YES;
  413.         remark ("GLOB");
  414.         return (OK);
  415.     }
  416. #endif
  417. #endif
  418.     if (lin[*i] == GMARK || lin[*i] == XMARK)    /* global markname prefix? */
  419.     {
  420.         if (lin[*i] == GMARK)    /* tag lines with the specified markname */
  421.             usemark = YES;
  422.         else            /* tag lines without the specified markname */
  423.             usemark = NO;
  424.         (*i)++;
  425.         *status = getkn (lin, i, &Savknm, Savknm);
  426.     }
  427.  
  428.     if (*status == OK)    /* check for a pattern prefix too */
  429.     {
  430.         if (lin[*i] == GLOBAL || lin[*i] == UCGLOBAL)
  431.             usepat = YES;
  432.  
  433.         if (lin[*i] == EXCLUDE || lin[*i] == UCEXCLUDE)
  434.             usepat = NO;
  435.  
  436.         if (usepat != EOF)
  437.         {
  438.             (*i)++;
  439.             if (optpat (lin, i) == ERR)
  440.                 *status = ERR;
  441.             else
  442.                 (*i)++;
  443.         }
  444.     }
  445.  
  446.     if (*status == OK && usepat == EOF && usemark == EOF)
  447.         *status = EOF;
  448.     else if (*status == OK)
  449.         defalt (1, Lastln);
  450.  
  451.     if (*status == OK)    /* no errors so far, safe to proceed */
  452.     {
  453.         remark ("GLOB");
  454.  
  455.         k = Line0;      /* unmark all lines preceeding range */
  456.         for (line = 0; line < Line1; line++)
  457.         {
  458.             k -> Globmark = NO;
  459.             k = NEXTLINE(k);
  460.         }
  461.  
  462.         for (; line <= Line2; line++)    /* mark lines in range */
  463.         {
  464.             if (intrpt ())
  465.             {
  466.                 *status = ERR;
  467.                 return (*status);
  468.             }
  469.             tmp = NO;
  470.             if (usemark == EOF
  471.                 || usemark == YES && k -> Markname == Savknm
  472.                 || usemark == NO && k -> Markname != Savknm)
  473.             {
  474.                 if (usepat == EOF)    /* no global pattern to look for */
  475.                     tmp = YES;
  476.                 else    /* there is also a pattern to look for */
  477.                 {
  478.                     gtxt (k);
  479.                     if (match (Txt, Pat) == usepat)
  480.                         tmp = YES;
  481.                 }
  482.             }
  483.  
  484.             k -> Globmark = tmp;
  485.  
  486.             k = NEXTLINE(k);
  487.         }
  488.  
  489. #ifdef OLD_SCRATCH
  490.         /* mark remaining lines */
  491.         for (; k != Line0; k = k -> Nextline)
  492.             k -> Globmark = NO;
  493. #else
  494.         /* mark remaining lines */
  495.         for (; line <= Lastln; line++)
  496.         {
  497.             k -> Globmark = NO;
  498.             k = NEXTLINE (k);
  499.         }
  500. #endif
  501.  
  502.         remark ("");
  503.     }
  504.  
  505.     return (*status);
  506. }
  507.  
  508.  
  509. /* doglob --- do command at lin[i] on all marked lines */
  510.  
  511. int doglob (lin, i, cursav, status)
  512. char lin[];
  513. int *i, *cursav, *status;
  514. {
  515.     register int istart, line;
  516.     int docmd (), getlst (), nextln ();
  517.     register LINEDESC *k;
  518.     LINEDESC *getind ();
  519.  
  520. #ifndef OLD_SCRATCH
  521. #ifndef OLD_GLOB
  522.     if (special_casing)
  523.     {
  524.         /*
  525.         remark ("Warp 7, Captain!");
  526.         */
  527.         /* not on the screen too long anyway */
  528.         reverse (1, Lastln);
  529.         Curln = Lastln;
  530.         special_casing = NO;
  531.         Buffer_changed = YES;
  532.         First_affected = min (1, First_affected);
  533.         remark ("");
  534.         adjust_window (Curln, Curln);
  535.         updscreen ();
  536.         return (OK);
  537.     }
  538. #endif
  539. #endif
  540.     *status = OK;
  541.     istart = *i;
  542.     k = Line0;
  543.     line = 0;
  544.  
  545.     do {
  546.         line++;
  547.         k = NEXTLINE(k);
  548.         if (k -> Globmark == YES)    /* line is marked */
  549.         {
  550.             k -> Globmark = NO;    /* unmark the line */
  551.             Curln = line;
  552.             *cursav = Curln;    /* remember where we are */
  553.             *i = istart;
  554.             if (getlst (lin, i, status) == OK)
  555.                 docmd (lin, *i, YES, status);
  556.             line = 0;        /* lines may have been moved */
  557.             k = Line0;
  558.         }
  559.         if (intrpt ())
  560.             *status = ERR;
  561.     } while (line <= Lastln && *status == OK);
  562.  
  563.     return (*status);
  564. }
  565.  
  566.  
  567. /* ckchar --- look for ch or altch on lin at i, set flag if found */
  568.  
  569. int ckchar (ch, altch, lin, i, flag, status)
  570. char ch, altch, lin[];
  571. int *i, *flag, *status;
  572. {
  573.  
  574.     if (lin[*i] == ch || lin[*i] == altch)
  575.     {
  576.         (*i)++;
  577.         *flag = YES;
  578.     }
  579.     else
  580.         *flag = NO;
  581.  
  582.     *status = OK;
  583.     return (OK);
  584. }
  585.  
  586.  
  587. /* ckp --- check for "p" after command */
  588.  
  589. int ckp (lin, i, pflag, status)
  590. char lin[];
  591. int i, *pflag, *status;
  592. {
  593.  
  594.     if (lin[i] == PRINT || lin[i] == UCPRINT)
  595.     {
  596.         i++;
  597.         *pflag = YES;
  598.     }
  599.     else
  600.         *pflag = NO;
  601.  
  602.     if (lin[i] == '\n')
  603.         *status = OK;
  604.     else
  605.         *status = ERR;
  606.  
  607.     return (*status);
  608. }
  609.  
  610.  
  611. /* ckupd --- make sure it is ok to destroy the buffer */
  612.  
  613. int ckupd (lin, i, cmd, status)
  614. char lin[], cmd;
  615. int *i, *status;
  616. {
  617.     int flag;
  618.     int ckchar ();
  619.  
  620.     *status = ckchar (ANYWAY, ANYWAY, lin, i, &flag, status);
  621.     if (flag == NO && Buffer_changed == YES && Probation != cmd)
  622.     {
  623.         *status = ERR;
  624.         Errcode = ESTUPID;
  625.         Probation = cmd;        /* if same command is repeated, */
  626.     }                       /* we'll keep quiet */
  627.  
  628.     return (*status);
  629. }
  630.  
  631.  
  632. /* defalt --- set defaulted line numbers */
  633.  
  634. defalt (def1, def2)
  635. int def1, def2;
  636. {
  637.  
  638.     if (Nlines == 0)        /* no line numbers supplied, use defaults */
  639.     {
  640.         Line1 = def1;
  641.         Line2 = def2;
  642.     }
  643.  
  644.     return;
  645. }
  646.  
  647.  
  648. /* getfn --- get file name from lin[i]... */
  649.  
  650. int getfn (lin, i, file)
  651. char lin[], file[];
  652. int i;
  653. {
  654.     int j, k, ret;
  655.  
  656.     ret = ERR;
  657.     if (lin[i + 1] == ' ')
  658.     {
  659.         j = i + 2;      /* get new file name */
  660.         SKIPBL (lin, j);
  661.         for (k = 0; lin[j] != NEWLINE; k++, j++)
  662.             file[k] = lin[j];
  663.         file[k] = EOS;
  664.         if (k > 0)
  665.             ret = OK;
  666.     }
  667.     else if (lin[i + 1] == '\n' && Savfil[0] != EOS)
  668.     {
  669.         strcpy (file, Savfil);    /* or old name */
  670.         ret = OK;
  671.     }
  672.     else 
  673.         if (lin[i + 1] == '\n')
  674.             Errcode = ENOFN;
  675.         else
  676.             Errcode = EFILEN;
  677.  
  678.     if (ret == OK && Savfil[1] == EOS)
  679.     {
  680.         strcpy (Savfil, file);        /* save if no old one */
  681.         mesg (Savfil, FILE_MSG);
  682.     }
  683.  
  684.     return (ret);
  685. }
  686.  
  687.  
  688. /* getkn --- get mark name from lin[i], increment i */
  689.  
  690. int getkn (lin, i, kname, dfltnm)
  691. char lin[], *kname, dfltnm;
  692. int *i;
  693. {
  694.  
  695.     if (lin[*i] == '\n' || lin[*i] == EOS)
  696.     {
  697.         *kname = dfltnm;
  698.         return (EOF);
  699.     }
  700.  
  701.     *kname = lin[*i];
  702.     (*i)++;
  703.     return (OK);
  704. }
  705.  
  706.  
  707. /* getrange --- get 'from' range for tlit command */
  708.  
  709. int getrange (array, k, set, size, allbut)
  710. char array[], set[];
  711. int *k, size, *allbut;
  712. {
  713.     int i, j;
  714.     int addset ();
  715.  
  716.     Errcode = EBADLIST;    /* preset error code */
  717.  
  718.     i = *k + 1;
  719.     if (array[i] == NOTINCCL)    /* check for negated character class */
  720.     {
  721.         *allbut = YES;
  722.         i++;
  723.     }
  724.     else
  725.         *allbut = NO;
  726.  
  727.     j = 0;
  728.     filset (array[*k], array, &i, set, &j, size);
  729.     if (array[i] != array[*k])
  730.     {
  731.         set[0] = EOS;
  732.         return (ERR);
  733.     }
  734.     if (set[0] == EOS)
  735.     {
  736.         Errcode = ENOLIST;
  737.         return (ERR);
  738.     }
  739.     if (j > 0 && addset (EOS, set, &j, size) == NO)
  740.     {
  741.         set[0] = EOS;
  742.         return (ERR);
  743.     }
  744.  
  745.     *k = i;
  746.     Errcode = EEGARB;
  747.  
  748.     return (OK);
  749. }
  750.  
  751.  
  752. /* getrhs --- get substitution string for 's' command */
  753.  
  754. int getrhs (lin, i, sub, gflag)
  755. char lin[], sub[];
  756. int *i, *gflag;
  757. {
  758.     static char Subs[MAXPAT] = "";    /* saved replacement pattern */
  759.     int j, maksub ();
  760.     /* saved replacement pattern char */
  761.  
  762.  
  763.     Errcode = EBADSUB;
  764.  
  765.     if (lin[*i] == EOS)    /* missing the middle delimeter */
  766.         return (ERR);
  767.  
  768.     if (lin[*i + 1] == '%' && (lin[*i + 2] == lin[*i]
  769.                     || lin[*i + 2] == '\n'))
  770.     {
  771.     /*
  772.      * s//%/ --- should mean do the same thing as I did last time, even
  773.      * s//&/ --- if I deleted something. So we comment out these lines.
  774.      *
  775.         if (Subs[0] == EOS)
  776.         {
  777.             Errcode = ENOSUB;
  778.             return (ERR);
  779.         }
  780.      */
  781.         strcpy (sub, Subs);
  782.         *i += 2;
  783.         if (lin[*i] == '\n')
  784.         {
  785.             /* fix it up for pattern matching routines */
  786.             lin[*i] = lin[*i - 2];
  787.             lin[*i + 1] = '\n';
  788.             lin[*i + 2] = EOS;
  789.             Peekc = SKIP_RIGHT;
  790.         }
  791.     }
  792.     else        /* not using saved substitution pattern */
  793.     {
  794.         if (lin[*i + 1] == '\n')
  795.         {
  796.             /* missing the trailing delimiter */
  797.             /* pattern was empty */
  798.             lin[*i + 1] = lin[*i];    /* supply missing delimiter */
  799.             lin[*i + 2] = '\n';
  800.             lin[*i + 3] = EOS;
  801.             Peekc = SKIP_RIGHT;
  802.             /* return (ERR);    /* this is the original action */
  803.         }
  804.         else
  805.         {
  806.             /* stuff in pattern, check end of line */
  807.             for (j = *i; lin[j] != EOS; j++)
  808.                 ;
  809.             j -= 2;        /* j now points to char before '\n' */
  810.  
  811.             if (lin[j] == 'p' || lin[j] == 'P')
  812.             {
  813.                 --j;
  814.                 if (lin[j] == GLOBAL || lin[j] == UCGLOBAL)
  815.                 {
  816.                     if (j >= *i + 1 && lin[j-1] == lin[*i]
  817.                         && (lin[j-2] != ESCAPE
  818.                             || lin[j-3] == ESCAPE))
  819.                         ;     /* leave alone */
  820.                     else
  821.                     {
  822.                         /* \<delim>gp\n is pattern */
  823.                         /* supply trailing delim */
  824.                         j +=  2;    /* j at \n */
  825.                         lin[j] = lin[*i];
  826.                         lin[++j] = '\n';
  827.                         lin[++j] = EOS;
  828.                         Peekc = SKIP_RIGHT;
  829.                     }
  830.                 }
  831.                 else if (j >= *i + 1 && lin[j] == lin[*i] &&
  832.                         (lin[j-1] != ESCAPE
  833.                          || lin[j-2] == ESCAPE))
  834.                     ;    /* leave alone */
  835.                 else
  836.                 {
  837.                     /* \<delim>p\n is pattern */
  838.                     /* supply trailing delim */
  839.                     j += 2;
  840.                     lin[j] = lin[*i];
  841.                     lin[++j] = '\n';
  842.                     lin[++j] = EOS;
  843.                     Peekc = SKIP_RIGHT;
  844.                 }
  845.             }
  846.             else if (lin[j] == GLOBAL || lin[j] == UCGLOBAL)
  847.             {
  848.                 --j;
  849.                 if (j >= *i + 1 && lin[j] == lin[*i] &&
  850.                     (lin[j-1] != ESCAPE
  851.                      || lin[j-2] == ESCAPE))
  852.                     ;     /* leave alone */
  853.                 else
  854.                 {
  855.                     /* \<delim>g\n is pattern */
  856.                     /* supply trailing delim */
  857.                     j +=  2;    /* j at \n */
  858.                     lin[j] = lin[*i];
  859.                     lin[++j] = '\n';
  860.                     lin[++j] = EOS;
  861.                     Peekc = SKIP_RIGHT;
  862.                 }
  863.             }
  864.             else if ((lin[j] != lin[*i]) ||
  865.                 (lin[j] == lin[*i] &&
  866.                 lin[j-1] == ESCAPE && lin[j-2] != ESCAPE))
  867.             {
  868.                 /* simply missing trailing delimeter */
  869.                 /* supply it */
  870.                 j++;        /* j at \n */
  871.                 lin[j] = lin[*i];
  872.                 lin[++j] = '\n';
  873.                 lin[++j] = EOS;
  874.                 Peekc = SKIP_RIGHT;
  875.             }
  876.             /* else
  877.                 unescaped delim is there,
  878.                 leave well enough alone */
  879.         }
  880.  
  881.         if ((*i = maksub (lin, *i + 1, lin[*i], sub)) == ERR)
  882.             return (ERR);
  883.  
  884.         strcpy (Subs, sub);    /* save pattern for later */
  885.     }
  886.  
  887.     if (lin[*i + 1] == GLOBAL || lin[*i + 1] == UCGLOBAL)
  888.     {
  889.         (*i)++;
  890.         *gflag = YES;
  891.     }
  892.     else
  893.         *gflag = NO;
  894.  
  895.     Errcode = EEGARB;    /* the default */
  896.  
  897.     return (OK);
  898.  
  899. }
  900.  
  901.  
  902. /* getstr --- get string from lin at i, copy to dst, bump i */
  903.  
  904. /*
  905. ** NOTE: this routine only called for doing the join command.
  906. ** therefore, don't do anything else with it.
  907. */
  908.  
  909. int getstr (lin, i, dst, maxdst)
  910. char lin[], dst[];
  911. int *i, maxdst;
  912. {
  913.     char delim;
  914.     char esc ();
  915.     int j, k, d;
  916.  
  917.     j = *i;
  918.     Errcode = EBADSTR;
  919.  
  920.     delim = lin[j];
  921.  
  922.     if (delim == '\n')
  923.     {
  924.         lin[j] = '/';
  925.         lin[++j] = ' ';        /* join with a single blank */
  926.         lin[++j] = '/';
  927.         lin[++j] = '\n';
  928.         lin[++j] = EOS;
  929.         j = *i;
  930.         delim = lin[j];
  931.         Peekc = SKIP_RIGHT;
  932.         /* now fall thru */
  933.  
  934.         /* return (ERR);    /* old way */
  935.     }
  936.     else if ((delim == 'p' || delim == 'P') && lin[j + 1] == '\n')    /* jp */
  937.     {
  938.         lin[j] = '/';
  939.         lin[++j] = ' ';        /* join with a single blank */
  940.         lin[++j] = '/';
  941.         lin[++j] = delim;    /* 'p' or 'P' */
  942.         lin[++j] = '\n';
  943.         lin[++j] = EOS;
  944.         j = *i;
  945.         delim = lin[j];
  946.         Peekc = SKIP_RIGHT;
  947.         /* now fall thru */
  948.     }
  949.  
  950.     if (lin[j + 1] == '\n')        /* command was 'j/' */
  951.     {
  952.         dst[0] = EOS;
  953.         Errcode = ENOERR;
  954.         return (OK);
  955.         /* return (ERR);    /* old way */
  956.     }
  957.  
  958.     /*
  959.      * otherwise, stuff there in the string, try to allow for
  960.      * a missing final delimiter.
  961.      */
  962.  
  963.     for (k = j + 1; lin[k] != '\n'; k++)
  964.         ;    /* find end */
  965.     
  966.     k--;    /* now points to char before newline */
  967.  
  968.     if (lin[k] == 'p' || lin[k] == 'P')
  969.     {
  970.         k--;
  971.         if (lin[k] == delim &&
  972.             (lin[k-1] != ESCAPE || lin[k-2] == ESCAPE))
  973.             ;    /* it's fine, leave it alone */
  974.         else
  975.         {
  976.             /* ESCAPE delim p NEWLINE is the join string */
  977.             /* supply trailing delimiter. */
  978.             k += 2;
  979.             lin[k] = delim;
  980.             lin[++k] = '\n';
  981.             lin[++k] = EOS;
  982.             Peekc = SKIP_RIGHT;
  983.         }
  984.     }
  985.     else if (lin[k] != delim || (lin[k-1] == ESCAPE && lin[k-2] != ESCAPE))
  986.     {
  987.         /* no delim and no p, or last char is escaped delim */
  988.         k++;
  989.         lin[k] = delim;
  990.         lin[++k] = '\n';
  991.         lin[++k] = EOS;
  992.         Peekc = SKIP_RIGHT;
  993.     }
  994.     /* else
  995.         delim is there
  996.         leave well enough alone */
  997.  
  998.     /* code to actually do the join */
  999.  
  1000.     for (k = j + 1; lin[k] != delim; k++)    /* find end */
  1001.     {
  1002.         if (lin[k] == '\n' || lin[k] == EOS)
  1003.             if (delim == ' ')
  1004.                 break;
  1005.             else
  1006.                 return (ERR);
  1007.         esc (lin, &k);
  1008.     }
  1009.     if (k - j > maxdst)
  1010.         return (ERR);
  1011.  
  1012.     for (d = 0, j++; j < k; d++, j++)
  1013.         dst[d] = esc (lin, &j);
  1014.     dst[d] = EOS;
  1015.  
  1016.     *i = j;
  1017.     Errcode = EEGARB;    /* the default */
  1018.  
  1019.     return (OK);
  1020. }
  1021.  
  1022.  
  1023. /* getwrd --- get next word from line at i; increment i */
  1024.  
  1025. int getwrd (line, i, word, size)
  1026. char line[], word[];
  1027. int *i, size;
  1028. {
  1029.     int j;
  1030.  
  1031.     SKIPBL (line, *i);
  1032.     j = 0;
  1033.     while (line[*i] != ' ' && line[*i] != '\n' && line[*i] != EOS)
  1034.     {
  1035.         if (j < size - 1)
  1036.         {
  1037.             word[j] = line[*i];
  1038.             j++;
  1039.         }
  1040.         (*i)++;
  1041.     }
  1042.     word[j] = EOS;
  1043.  
  1044.     return (j);
  1045. }
  1046.  
  1047.  
  1048. /* knscan --- scan for a line with a given mark name */
  1049.  
  1050. int knscan (way, num)
  1051. int way, *num;
  1052. {
  1053.     int nextln ();
  1054.     LINEDESC *k;
  1055.     LINEDESC *getind ();
  1056.  
  1057.     *num = Curln;
  1058.     k = getind (*num);
  1059.     do {
  1060.         bump (num, &k, way);
  1061.         if (k -> Markname == Savknm)
  1062.             return (OK);
  1063.     } while (*num != Curln && ! intrpt ());
  1064.  
  1065.     if (Errcode = EEGARB)
  1066.         Errcode = EKNOTFND;
  1067.     return (ERR);
  1068.  
  1069. }
  1070.  
  1071.  
  1072. /* makset --- make set from array[k] in set */
  1073.  
  1074. int makset (array, k, set, size)
  1075. char array[], set[];
  1076. int *k, size;
  1077. {
  1078.     static char Tset[MAXPAT] = "";    /* saved translit dest range */
  1079.     int i, j;
  1080.     int l;
  1081.     int addset ();
  1082.  
  1083.     Errcode = EBADLIST;
  1084.  
  1085.     /*
  1086.      * try to allow missing delimiter for translit command.
  1087.      */
  1088.     
  1089.     if (array[*k] == EOS)
  1090.         return (ERR);
  1091.  
  1092.     if (array[*k + 1] == '%' && (array[*k + 2] == array[*k]
  1093.                        || array[*k + 2] == '\n'))
  1094.     {
  1095.         strcpy (set, Tset);
  1096.         *k += 2;
  1097.         if (array[*k] == '\n')
  1098.         {
  1099.             /* fix it up for rest of the routines */
  1100.             array[*k] = array[*k - 2];
  1101.             array[*k+ 1] = '\n';
  1102.             array[*k+ 2] = EOS;
  1103.         }
  1104.         Peekc = SKIP_RIGHT;
  1105.     }
  1106.     else
  1107.     {
  1108.     
  1109.         for (l = *k; array[l] != EOS; l++)
  1110.             ;
  1111.         l -= 2;        /* l now points to char before '\n' */
  1112.     
  1113.         if (l == *k)    /* "y/.../\n" */
  1114.         {
  1115.             array[*k + 1] = array[*k];    /* add delimiter */
  1116.             array[*k + 2] = '\n';
  1117.             array[*k + 3] = EOS;
  1118.             Peekc = SKIP_RIGHT;
  1119.         }
  1120.         else if (array[l] == 'p' || array[l] == 'P')
  1121.         {
  1122.             --l;
  1123.             if (l >= *k + 1 && array[l] == array[*k] &&
  1124.                 (array[l-1] != ESCAPE || array[l-2] == ESCAPE))
  1125.                 ;    /* leave alone */
  1126.             else
  1127.             {
  1128.                 /* \<delim>p\n is set */
  1129.                 /* supply trailing delim */
  1130.                 l += 2;
  1131.                 array[l] = array[*k];
  1132.                 array[++l] = '\n';
  1133.                 array[++l] = EOS;
  1134.                 Peekc = SKIP_RIGHT;
  1135.             }
  1136.         }
  1137.         else if (array[l] != array[*k]    /* no delim, and no p */
  1138.             || (array[l-1] == ESCAPE    /* or last char is escaped delim */
  1139.             && array[l-2] != ESCAPE))
  1140.         {
  1141.             /* simply missing trailing delimeter */
  1142.             /* supply it */
  1143.             l++;        /* l now at \n */
  1144.             array[l] = array[*k];
  1145.             array[++l] = '\n';
  1146.             array[++l] = EOS;
  1147.             Peekc = SKIP_RIGHT;
  1148.         }
  1149.         /* else
  1150.             delim is there,
  1151.             leave well enough alone */
  1152.  
  1153.         j = 0;
  1154.         i = *k + 1;
  1155.         filset (array[*k], array, &i, set, &j, size);
  1156.  
  1157.         if (array[i] != array[*k])
  1158.             return (ERR);
  1159.  
  1160.         if (addset (EOS, set, &j, size) == NO)
  1161.             return (ERR);
  1162.  
  1163.         strcpy (Tset, set);    /* save for later */
  1164.         *k = i;
  1165.  
  1166.     }
  1167.  
  1168.     Errcode = EEGARB;
  1169.  
  1170.     return (OK);
  1171. }
  1172.  
  1173.  
  1174. /* optpat --- make pattern specified at lin[i] */
  1175.  
  1176. int optpat (lin, i)
  1177. char lin[];
  1178. int *i;
  1179. {
  1180.     int makpat ();
  1181.  
  1182.     if (lin[*i] == EOS)
  1183.         *i = ERR;
  1184.     else if (lin[*i + 1] == EOS)
  1185.         *i = ERR;
  1186.     else if (lin[*i + 1] == lin[*i])    /* repeated delimiter */
  1187.         (*i)++;        /* leave existing pattern alone */
  1188.     else
  1189.         *i = makpat (lin, *i + 1, lin[*i], Pat);
  1190.  
  1191.     if (Pat [0] == EOS)
  1192.     {
  1193.         Errcode = ENOPAT;
  1194.         return (ERR);
  1195.     }
  1196.     if (*i == ERR)
  1197.     {
  1198.         Pat[0] = EOS;
  1199.         Errcode = EBADPAT;
  1200.         return (ERR);
  1201.     }
  1202.     return (OK);
  1203. }
  1204.  
  1205.  
  1206. /* ptscan --- scan for next occurrence of pattern */
  1207.  
  1208. int ptscan (way, num)
  1209. int way, *num;
  1210. {
  1211.     LINEDESC *getind ();
  1212.     LINEDESC *k;
  1213.     int match ();
  1214.  
  1215.     *num = Curln;
  1216.     k = getind (*num);
  1217.     do {
  1218.         bump (num, &k, way);
  1219.         gtxt (k);
  1220.         if (match (Txt, Pat) == YES)
  1221.             return (OK);
  1222.     } while (*num != Curln && ! intrpt ());
  1223.  
  1224.     if (Errcode == EEGARB)
  1225.         Errcode = EPNOTFND;
  1226.  
  1227.     return (ERR);
  1228. }
  1229.  
  1230.  
  1231. /* settab --- set tab stops */
  1232.  
  1233. int settab (str)
  1234. char str[];
  1235. {
  1236.     int i, j, n, maxstop, last, inc, ret;
  1237.     int ctoi ();
  1238.  
  1239.     for (i = 0; i < MAXLINE; i++)   /* clear all tab stops */
  1240.         Tabstops[i] = NO;
  1241.  
  1242.     ret = OK;
  1243.     maxstop = 0;
  1244.     last = 1;
  1245.  
  1246.     i = 0;
  1247.     SKIPBL (str, i);
  1248.     while (str[i] != EOS && str[i] != '\n')
  1249.     {
  1250.         if (str[i] == '+')      /* increment */
  1251.         {
  1252.             i++;
  1253.             inc = YES;
  1254.         }
  1255.         else
  1256.             inc = NO;
  1257.  
  1258.         n = ctoi (str, &i);
  1259.  
  1260.         if (n <= 0 || n >= MAXLINE)
  1261.         {
  1262.             ret = ERR;
  1263.             Errcode = ENONSENSE;
  1264.             break;
  1265.         }
  1266.  
  1267.         if (str[i] != ' ' && str[i] != '+' &&
  1268.             str[i] != '\n' && str[i] != EOS)
  1269.         {
  1270.             ret = ERR;
  1271.             Errcode = EBADTABS;
  1272.             break;
  1273.         }
  1274.  
  1275.         if (inc == YES)
  1276.         {
  1277.             for (j = last + n; j < MAXLINE; j += n)
  1278.             {
  1279.                 Tabstops[j - 1] = YES;
  1280.                 maxstop = max (j, maxstop);
  1281.             }
  1282.         }
  1283.         else
  1284.         {
  1285.             Tabstops[n - 1] = YES;
  1286.             last = n;
  1287.             maxstop = max (n, maxstop);
  1288.         }
  1289.         SKIPBL (str, i);
  1290.     }       /* while ... */
  1291.  
  1292.     if (ret == ERR)
  1293.         maxstop = 0;
  1294.  
  1295.     if (maxstop == 0)       /* no tab stops specified, use defaults */
  1296.     {
  1297.         for (i = 4; i < MAXLINE - 1; i += 4)
  1298.             Tabstops[i] = YES;
  1299.         maxstop = i - 4 + 1;
  1300.     }
  1301.  
  1302.     Tabstops[0] = YES;      /* always set to YES */
  1303.  
  1304.     for (i = maxstop; i < MAXLINE; i++)
  1305.         Tabstops[i] = YES;
  1306.  
  1307.     return (ret);
  1308. }
  1309.  
  1310. /* serc --- read in ./.serc or $HOME/.serc and execute the commands in it. */
  1311.  
  1312. /*
  1313.  * note that se's special control characters are NOT processed,
  1314.  * and therefore should NOT be used in one's .serc file.
  1315.  */
  1316.  
  1317. static serc ()
  1318. {
  1319.     char file[MAXLINE];
  1320.     char lin[MAXLINE];
  1321.     char *expand_env ();
  1322.     FILE *fp;
  1323.     int status = ENOERR;
  1324.     int len, cursav;
  1325.  
  1326.     strcpy (file, expand_env ("$HOME/.serc"));
  1327.  
  1328.     if ((fp = fopen ("./.serc", "r")) == NULL ||
  1329.             (fp = fopen (file, "r")) == NULL)
  1330.         return;
  1331.     
  1332.     while (fgets (lin, sizeof lin, fp) != NULL && status != EOF /*??*/)
  1333.     {
  1334.         if (lin[0] == '#' || lin[0] == '\n')
  1335.             continue;    /* comment in .serc file */
  1336.  
  1337.         /* most of this code stolen from edit() */
  1338.         len = 0;
  1339.         cursav = Curln;
  1340.         if (getlst (lin, &len, &status) == OK)
  1341.         {
  1342.             if (ckglob (lin, &len, &status) == OK)
  1343.                 doglob (lin, &len, &cursav, &status);
  1344.             else if (status != ERR)
  1345.                 docmd (lin, len, NO, &status);
  1346.         }
  1347.         if (status == ERR)
  1348.         {
  1349.             if (Errcode == EHANGUP)
  1350.                 hangup ();
  1351.             Curln = min (cursav, Lastln);
  1352.         }
  1353.     }
  1354.     fclose (fp);
  1355. }
  1356.  
  1357. #ifdef LOG_USAGE
  1358.  
  1359. /* log -- log se usage */
  1360.  
  1361.  
  1362. static log ()
  1363. {
  1364.     static char logfile[] = "/usr/tmp/se.log";    /* a public file */
  1365.     char logname[MAXLINE], tod[26];        /* tod => time of day */
  1366.     long clock;
  1367.     FILE *fp;
  1368.     char *ctime ();
  1369.     long time ();
  1370.     int old_umask;
  1371. #ifdef BSD
  1372.     char *getlogin ();
  1373. #else
  1374.     char *cuserid ();
  1375. #endif
  1376.  
  1377.     /* get the login name */
  1378. #ifdef BSD
  1379.     strcpy (logname, getlogin ());
  1380. #else
  1381.     cuserid (logname);
  1382. #endif
  1383.  
  1384.     time (&clock);
  1385.     strcpy (tod, ctime (&clock));    /* see the manual on ctime(3C)  */
  1386.     tod[24] = EOS;            /* delete the '\n' at the end */
  1387.  
  1388.     old_umask = umask (0);        /* allow writes for everyone */
  1389.                     /* when first call creates the file */
  1390.  
  1391.     if ((fp = fopen (logfile, "a")) != NULL)
  1392.     {
  1393.         /* all ok, write out statistics */
  1394.         fprintf (fp, "%s used se on %s.\n", logname, tod);
  1395.         fclose (fp);
  1396.     }
  1397.     /* else
  1398.         don't do anything */
  1399.  
  1400.     umask (old_umask);
  1401.  
  1402. }
  1403. #endif
  1404.  
  1405. /* sysname --- return a string telling us who we are */
  1406.  
  1407. #ifdef USG
  1408. #include <sys/utsname.h>    /* stuff to find out who we are */
  1409. #endif
  1410.  
  1411. char *sysname ()
  1412. {
  1413.     int i, j, k;
  1414.     char c;
  1415.     static char buf[MAXLINE] = "";
  1416.     FILE *fp;
  1417.     static char unknown[] = "unknown";
  1418.  
  1419. #ifdef USG    /* System V */
  1420.     static struct utsname whoarewe;
  1421.  
  1422.     uname (& whoarewe);
  1423.     return (whoarewe.nodename);
  1424. #else
  1425. #ifdef BSD4_2    /* Berkeley 4.2 */
  1426.     if (buf[0] != EOS)
  1427.         return (buf);
  1428.  
  1429.     j = sizeof (buf);
  1430.     k = gethostname (buf, & j);
  1431.     if (k != 0)
  1432.         return (unknown);
  1433.     else
  1434.         return (buf);
  1435. #else        /* Berkeley 4.1 */
  1436.     if (buf[0] != EOS)
  1437.         return (buf);
  1438.  
  1439.     if ((fp = fopen ("/usr/include/whoami.h", "r")) == NULL)
  1440.         return (unknown);
  1441.     else
  1442.     {
  1443.         auto char *cp;
  1444.         /*
  1445.          * file should contain a single line:
  1446.          * #define sysname "......"
  1447.          */
  1448.         while ((c = getc (fp)) != '"' && c != EOF)
  1449.             ;
  1450.         if (c == EOF)
  1451.             cp = unknown;
  1452.         else
  1453.         {
  1454.             for (i = 0; (c = getc (fp)) != '"' && c != EOF; i++)
  1455.                 buf[i] = c;
  1456.             buf[i] = EOS;
  1457.             if (c == EOF && i == 0)
  1458.                 cp = unknown;
  1459.             else
  1460.                 cp = buf;
  1461.         }
  1462.         fclose (fp);
  1463.         return (cp);
  1464.     }
  1465. #endif
  1466. #endif
  1467. }
  1468. SHAR_EOF
  1469. fi # end of overwriting check
  1470. echo shar: extracting "'extern.h'" '(4770 characters)'
  1471. if test -f 'extern.h'
  1472. then
  1473.     echo shar: will not over-write existing file "'extern.h'"
  1474. else
  1475. cat << \SHAR_EOF > 'extern.h'
  1476. /*
  1477.  * $Header: extern.h,v 1.2 86/07/14 16:44:30 arnold Exp $
  1478.  */
  1479.  
  1480. /*
  1481.  * $Log:    extern.h,v $
  1482.  * Revision 1.2  86/07/14  16:44:30  arnold
  1483.  * Removed stuff that was Georgia Tech specific.
  1484.  * 
  1485.  * Revision 1.1  86/05/06  13:36:05  osadr
  1486.  * Initial revision
  1487.  * 
  1488.  * 
  1489.  */
  1490.  
  1491. /*
  1492. ** extern.h
  1493. **
  1494. ** external data definitions
  1495. ** for the screen editor
  1496. */
  1497.  
  1498. /* Concerning line numbers: */
  1499. extern int Line1;        /* first line number on command */
  1500. extern int Line2;        /* second line number on command */
  1501. extern int Nlines;        /* number of line numbers specified */
  1502. extern int Curln;        /* current line; value of dot */
  1503. extern int Lastln;        /* last line; value of dollar */
  1504.  
  1505.  
  1506. /* Concerning patterns: */
  1507. extern char Pat[MAXPAT];    /* saved pattern */
  1508.  
  1509.  
  1510. /* Concerning the text of lines: */
  1511. extern char Txt[MAXLINE];    /* text of current line */
  1512.  
  1513.  
  1514. /* Concerning file names: */
  1515. extern char Savfil[MAXLINE];    /* remembered file name */
  1516.  
  1517.  
  1518. /* Concerning line descriptors: */
  1519. extern LINEDESC Buf[MAXBUF];
  1520. #ifdef OLD_SCRATCH
  1521. extern LINEDESC *Lastbf;    /* last pointer used in Buf */
  1522. extern LINEDESC *Free;        /* head of free list */
  1523. #endif
  1524. extern LINEDESC *Line0;        /* head of list of line descriptors */
  1525.  
  1526.  
  1527. /* Concerning the 'undo' command: */
  1528. extern LINEDESC *Limbo;        /* head of limbo list for undo */
  1529. extern int Limcnt;        /* number of lines in limbo list */
  1530.  
  1531.  
  1532. /* Concerning the scratch file: */
  1533. extern filedes Scr;        /* scratch file descriptor */
  1534. extern unsigned Scrend;        /* end of info on scratch file */
  1535. extern char Scrname[MAXLINE];    /* name of scratch file */
  1536. extern int Lost_lines;        /* number of garbage lines in scratch file */
  1537.  
  1538.  
  1539. /* Concerning miscellaneous variables */
  1540. extern int Buffer_changed;    /* YES if buffer changed since last write */
  1541. extern int Errcode;        /* cause of most recent error */
  1542. extern int Saverrcode;        /* cause of previous error */
  1543. extern int Probation;        /* YES if unsaved buffer can be destroyed */
  1544. extern int Argno;        /* command line argument pointer */
  1545. extern char Last_char_scanned;    /* last char scanned with ctl-s or -l */
  1546. #ifdef HARD_TERMS
  1547. extern int Tspeed;        /* terminal speed in characters/second */
  1548. #endif
  1549. extern char Peekc;        /* push a SKIP_RIGHT if adding delimiters */
  1550. #ifdef BSD4_2
  1551. extern int Reading;        /* are we doing terminal input? */
  1552. #endif
  1553.  
  1554.  
  1555. /* Concerning options: */
  1556. extern int Tabstops[MAXLINE];    /* array of tab stops */
  1557. extern char Unprintable;    /* char to print for unprintable chars */
  1558. extern int Absnos;        /* use absolute numbers in margin */
  1559. extern int Nchoise;        /* choice of line number for cont. display */
  1560. extern int Overlay_col;        /* initial cursor column for 'v' command */
  1561. extern int Warncol;        /* where to turn on column warning */
  1562. extern int Firstcol;        /* leftmost column to display */
  1563. extern int Indent;        /* indent col; 0=same as previous line */
  1564. extern int Notify;        /* notify user if he has mail in mail file */
  1565. extern int Globals;        /* substitutes in a global don't fail */
  1566. extern int No_hardware;        /* never use hardware insert/delete */
  1567.  
  1568.  
  1569. #ifdef HARD_TERMS
  1570. /* Concerning the terminal type */
  1571. extern int Term_type;          /* terminal type */
  1572. #endif
  1573.  
  1574.  
  1575. /* Concerning the screen format: */
  1576. extern char Screen_image[MAXROWS][MAXCOLS];
  1577. extern char Msgalloc[MAXCOLS];    /* column allocation of status line */
  1578. extern int Nrows;        /* number of rows on screen */
  1579. extern int Ncols;        /* number of columns on screen */
  1580. extern int Currow;        /* vertical cursor coordinate */
  1581. extern int Curcol;        /* horizontal cursor coordinate */
  1582. extern int Toprow;        /* top row of window field on screen */
  1583. extern int Botrow;        /* bottom row of window field on screen */
  1584. extern int Cmdrow;        /* row number of command line */
  1585. extern int Topln;        /* line number of first line on screen */
  1586. extern int Insert_mode;        /* flag to specify character insertion */
  1587. extern int Invert_case;        /* flag to specify case mapping on input */
  1588. extern int First_affected;    /* number of first line affected by cmd */
  1589. extern int Rel_a;        /* char to use for first alpha line number */
  1590. extern int Rel_z;        /* char to use for last alpha line number */
  1591. extern int Scline[MAXROWS];    /* lines currently on screen (rel to Sctop) */
  1592. extern int Sctop;        /* first line currently on screen */
  1593. extern int Sclen;        /* number of lines currently on screen */
  1594. extern char Blanks[MAXCOLS];    /* all blanks for filling in lines on screen */
  1595. extern char Tobuf[MAXTOBUF];    /* buffer for collecting terminal output */
  1596. extern char *Tobp;        /* pointer to last used part of Tobuf */
  1597.  
  1598.  
  1599. /* Concerning interrupts: */
  1600. extern int Int_caught;        /* caught a SIGINT from user */
  1601. extern int Hup_caught;        /* caught a SIGHUP when phone line dropped */
  1602. #ifdef SIGTSTP
  1603. extern int Catching_stops;    /* catching or ignoring SIGTSTP's? */
  1604. #endif
  1605.  
  1606. /* Concerning file encryption: */
  1607. extern int Crypting;        /* doing file encryption? */
  1608. extern char Key[KEYSIZE];    /* encryption key */
  1609. SHAR_EOF
  1610. fi # end of overwriting check
  1611. echo shar: extracting "'m4munge'" '(704 characters)'
  1612. if test -f 'm4munge'
  1613. then
  1614.     echo shar: will not over-write existing file "'m4munge'"
  1615. else
  1616. cat << \SHAR_EOF > 'm4munge'
  1617. #! /bin/sh
  1618. # m4munge --- take what the 'where' command produces, and change it for m4
  1619. # $Header: m4munge,v 1.2 86/07/11 15:13:56 osadr Exp $
  1620. # $Log:    m4munge,v $
  1621. # Revision 1.2  86/07/11  15:13:56  osadr
  1622. # Removed Georgia Tech specific items.
  1623. # Revision 1.1  86/05/06  13:35:02  osadr
  1624. # Initial revision
  1625.  
  1626. for i in $*
  1627. do
  1628.     case $i in
  1629.     -DUSG)        echo 'define(USG,YES)'        ;;
  1630.     -UUSG)        echo 'define(USG,NO)'        ;;
  1631.     -DBSD)        echo 'define(BSD,YES)'        ;;
  1632.     -UBSD)        echo 'define(BSD,NO)'        ;;
  1633.     -DBSD4_2)    echo 'define(BSD4_2,YES)'    ;;
  1634.     -UBSD4_2)    echo 'define(BSD4_2,NO)'    ;;
  1635.     -DS5R2)        echo 'define(S5R2,YES)'        ;;
  1636.     -US5R2)        echo 'define(S5R2,NO)'        ;;
  1637.     -DHARD_TERMS)    echo 'define(HARD_TERMS,YES)'    ;;
  1638.     esac
  1639. done
  1640. SHAR_EOF
  1641. chmod +x 'm4munge'
  1642. fi # end of overwriting check
  1643. echo shar: extracting "'main.c'" '(13208 characters)'
  1644. if test -f 'main.c'
  1645. then
  1646.     echo shar: will not over-write existing file "'main.c'"
  1647. else
  1648. cat << \SHAR_EOF > 'main.c'
  1649. #ifndef lint
  1650. static char RCSid[] = "$Header: main.c,v 1.4 86/10/07 14:50:17 arnold Exp $";
  1651. #endif
  1652.  
  1653. /*
  1654.  * $Log:    main.c,v $
  1655.  * Revision 1.4  86/10/07  14:50:17  arnold
  1656.  * Changed setterm to set_term, to avoid Unix/PC shared library conflict.
  1657.  * 
  1658.  * Revision 1.3  86/07/17  17:20:58  arnold
  1659.  * Terminal initialization code cleaned up considerably.
  1660.  * 
  1661.  * Revision 1.2  86/07/11  15:12:26  osadr
  1662.  * Removed code that was Georgia Tech specific
  1663.  * 
  1664.  * Revision 1.1  86/05/06  13:37:38  osadr
  1665.  * Initial revision
  1666.  * 
  1667.  * 
  1668.  */
  1669.  
  1670. /*
  1671. ** main.c
  1672. **
  1673. ** main program and lots of other routines
  1674. ** for the se screen editor.
  1675. */
  1676.  
  1677. #include "se.h"
  1678.  
  1679. /* declare global variables */
  1680.  
  1681. /* Concerning line numbers: */
  1682. int Line1;        /* first line number on command */
  1683. int Line2;        /* second line number on command */
  1684. int Nlines;        /* number of line numbers specified */
  1685. int Curln;        /* current line; value of dot */
  1686. int Lastln;        /* last line; value of dollar */
  1687.  
  1688.  
  1689. /* Concerning patterns: */
  1690. char Pat[MAXPAT] = "";    /* saved pattern */
  1691.  
  1692.  
  1693. /* Concerning the text of lines: */
  1694. char Txt[MAXLINE];    /* text of current line */
  1695.  
  1696.  
  1697. /* Concerning file names: */
  1698. char Savfil[MAXLINE] = "";    /* remembered file name */
  1699.  
  1700.  
  1701. /* Concerning line descriptors: */
  1702. LINEDESC Buf[MAXBUF];
  1703. LINEDESC *Line0;    /* head of list of line descriptors */
  1704. #ifdef OLD_SCRATCH
  1705. LINEDESC *Lastbf;    /* last pointer used in Buf */
  1706. LINEDESC *Free;        /* head of free list */
  1707. #endif
  1708.  
  1709.  
  1710. /* Concerning the 'undo' command: */
  1711. LINEDESC *Limbo;    /* head of limbo list for undo */
  1712. int Limcnt;        /* number of lines in limbo list */
  1713.  
  1714.  
  1715. /* Concerning the scratch file: */
  1716. filedes Scr;        /* scratch file descriptor */
  1717. unsigned Scrend;    /* end of info on scratch file */
  1718. char Scrname[MAXLINE];    /* name of scratch file */
  1719. int Lost_lines;        /* number of garbage lines in scratch file */
  1720.  
  1721.  
  1722. /* Concerning miscellaneous variables */
  1723. int Buffer_changed = NO;/* YES if buffer changed since last write */
  1724. int Errcode = ENOERR;    /* cause of most recent error */
  1725. int Saverrcode = ENOERR;/* cause of previous error */
  1726. int Probation = NO;    /* YES if unsaved buffer can be destroyed */
  1727. int Argno;        /* command line argument pointer */
  1728. char Last_char_scanned = 0;    /* last char scanned w/ctl-[sl], init illegal  */
  1729. char Peekc = EOS;    /* push a SKIP_RIGHT if adding delimiters */
  1730. #ifdef HARD_TERMS
  1731. int Tspeed;        /* terminal speed in characters/second */
  1732. #endif
  1733. #ifdef BSD4_2
  1734. int Reading = NO;    /* are we doing terminal input? */
  1735. #endif
  1736.  
  1737.  
  1738. /* Concerning options: */
  1739. int Tabstops[MAXLINE];    /* array of tab stops */
  1740. char Unprintable = ' ';    /* char to print for unprintable chars */
  1741. int Absnos = NO;    /* use absolute numbers in margin */
  1742. int Nchoise = EOS;    /* choice of line number for cont. display */
  1743. int Overlay_col = 0;    /* initial cursor column for 'v' command */
  1744. int Warncol;        /* where to turn on column warning, set in dosopt() */
  1745. int Firstcol = 0;    /* leftmost column to display */
  1746. int Indent = 1;        /* indent col; 0=same as previous line */
  1747. int Notify = YES;    /* notify user if he has mail in mail file */
  1748. int Globals = NO;    /* substitutes in a global don't fail */
  1749. int No_hardware;    /* never use hardware insert/delete */
  1750.  
  1751.  
  1752. #ifdef HARD_TERMS
  1753. /* Concerning the terminal type */
  1754. int Term_type;        /* terminal type */
  1755. #endif
  1756.  
  1757.  
  1758. /* Concerning the screen format: */
  1759. char Screen_image[MAXROWS][MAXCOLS];
  1760. char Msgalloc[MAXCOLS];    /* column allocation of status line */
  1761. int Nrows;        /* number of rows on screen */
  1762. int Ncols;        /* number of columns on screen */
  1763. int Currow;        /* vertical cursor coordinate */
  1764. int Curcol;        /* horizontal cursor coordinate */
  1765. int Toprow;        /* top row of window field on screen */
  1766. int Botrow;        /* bottom row of window field on screen */
  1767. int Cmdrow;        /* row number of command line */
  1768. int Topln;        /* line number of first line on screen */
  1769. int Insert_mode;    /* flag to specify character insertion */
  1770. int Invert_case;    /* flag to specify case mapping on input */
  1771. int First_affected;    /* number of first line affected by cmd */
  1772. int Rel_a;        /* char to use for first alpha line number */
  1773. int Rel_z;        /* char to use for last alpha line number */
  1774. int Scline[MAXROWS];    /* lines currently on screen (rel to Sctop) */
  1775. int Sctop;        /* first line currently on screen */
  1776. int Sclen;        /* number of lines currently on screen */
  1777. char Blanks[MAXCOLS];    /* all blanks for filling in lines on screen */
  1778. char Tobuf[MAXTOBUF];    /* buffer for collecting terminal output */
  1779. char *Tobp = Tobuf - 1;    /* pointer to last used part of Tobuf */
  1780.  
  1781.  
  1782. /* Concerning interrupts: */
  1783. int Int_caught = 0;    /* caught a SIGINT from user */
  1784. int Hup_caught = 0;    /* caught a SIGHUP when phone line dropped */
  1785. #ifdef BSD
  1786. int Catching_stops;    /* catching or ignoring SIGTSTP's? */
  1787. #endif
  1788.  
  1789. /* Concerning file encryption: */
  1790. int Crypting = NO;    /* doing file encryption? */
  1791. char Key[KEYSIZE] = "";    /* saved encryption key */
  1792.  
  1793. extern char *getenv ();
  1794.  
  1795. /* main --- main program for screen editor */
  1796.  
  1797. main (argc, argv)
  1798. int argc;
  1799. char *argv[];
  1800. {
  1801.     char *basename ();
  1802.     int int_hdlr (), hup_hdlr ();
  1803.     int (*old_int)(), (*old_quit)();
  1804. #ifdef BSD
  1805.     int stop_hdlr (), (*old_stop)();
  1806. #endif
  1807.     /* catch quit and hangup signals */
  1808.     /*
  1809.      * In the terminal driver munging routines, we set Control-P
  1810.      * to generate an interrupt, and turn off generating Quits from
  1811.      * the terminal.  Now we just ignore them if sent from elsewhere.
  1812.      */
  1813.  
  1814.     signal (SIGHUP, hup_hdlr);
  1815.  
  1816.     old_int = signal (SIGINT, int_hdlr);
  1817.     old_quit = signal (SIGQUIT, SIG_IGN);
  1818.  
  1819. #ifdef notdef
  1820. /*
  1821.  * This is commented out so that se can be run from the news
  1822.  * software.  Commenting it out will also allow you to put it
  1823.  * in the background, which could give you trouble. So beware.
  1824.  */
  1825.  
  1826.     if (old_int == SIG_IGN || old_quit == SIG_IGN)
  1827.     {
  1828.         /* fired off into the background, refuse to run */
  1829.         if (isatty (fileno (stdin)))
  1830.         {
  1831.             fprintf (stderr, "%s: I refuse to run in the background.\n",
  1832.                 basename (argv[0]));
  1833.             exit (2);
  1834.         }
  1835.         /* else
  1836.             assume input is a script */
  1837.     }
  1838. #endif
  1839.  
  1840. #ifdef BSD
  1841.     old_stop = signal (SIGTSTP, stop_hdlr);
  1842.  
  1843.     if (old_stop == SIG_IGN)    /* running bourne shell */
  1844.     {
  1845.         signal (SIGTSTP, SIG_IGN);    /* restore it */
  1846.         Catching_stops = NO;
  1847.     }
  1848.     else
  1849.         Catching_stops = YES;
  1850.         /* running C-shell or BRL sh, catch Control-Z's */
  1851. #endif
  1852.  
  1853.     /* set terminal to no echo, no output processing, break enabled */
  1854.     ttyedit ();
  1855.  
  1856. #ifdef HARD_TERMS
  1857.     Tspeed = getspeed (1);        /* speed of stdout */
  1858. #endif
  1859.  
  1860.     initialize (argc, argv);
  1861.  
  1862.     edit (argc, argv);
  1863.  
  1864. #ifndef HARD_TERMS
  1865.     t_exit ();
  1866. #endif
  1867.  
  1868.     /* reset the terminal mode */
  1869.     ttynormal ();
  1870. }
  1871.  
  1872. /* error --- print error message and die semi-gracefully */
  1873.  
  1874. error (coredump, msg)
  1875. int coredump;
  1876. char *msg;
  1877. {
  1878.     /*
  1879.      * You might think we want to try and save the buffer,
  1880.      * BUT, fatal errors can be caused by buffer problems,
  1881.      * which would end up putting us into a non-ending recursion.
  1882.      */
  1883.  
  1884.     ttynormal ();
  1885.     fprintf (stderr, "%s\n", msg);
  1886.     signal (SIGQUIT, SIG_DFL);    /* restore normal quit handling */
  1887.     if (coredump)
  1888.         kill (getpid (), SIGQUIT);    /* dump memory */
  1889.     else
  1890.         exit (1);
  1891. }
  1892.  
  1893. /* initialize --- set up global data areas, get terminal type */
  1894.  
  1895. initialize (argc, argv)
  1896. int argc;
  1897. char *argv[];
  1898. {
  1899.     int i, dosopt ();
  1900.  
  1901.     Argno = 1;
  1902. #ifdef HARD_TERMS
  1903.     /* Determine what type of terminal we're on */
  1904.     if (Argno < argc && argv[Argno][0] == '-' && argv[Argno][2] == EOS
  1905.         && (argv[Argno][1] == 't' || argv[Argno][1] == 'T'))
  1906.     {
  1907.         Argno = 2;
  1908.         if (Argno < argc)
  1909.         {
  1910.             strmap (argv[Argno], 'l');
  1911.             if (set_term (argv[Argno]) == ERR)
  1912.                 usage ();
  1913.             else
  1914.                 Argno++;
  1915.         }
  1916.         else
  1917.             usage ();
  1918.     }
  1919.     else
  1920.         /* fall through to the if, below */
  1921. #endif
  1922.         if (set_term (getenv ("TERM")) == ERR)
  1923.             usage ();
  1924.  
  1925.     /* Initialize the scratch file: */
  1926.     mkbuf ();
  1927.  
  1928.     /* Initialize screen format parameters: */
  1929.     setscreen ();
  1930.  
  1931.     /* Initialize the array of blanks to blanks */
  1932.     for (i = 0; i < Ncols; i++)
  1933.         Blanks[i] = ' ';
  1934.     Blanks[i] = '\0';
  1935.  
  1936.     if (dosopt ("") == ERR)
  1937.         error ("in initialize: can't happen");
  1938. }
  1939.  
  1940. /* intrpt --- see if there has been an interrupt or hangup */
  1941.  
  1942. int intrpt ()
  1943. {
  1944.     if (Int_caught)
  1945.     {
  1946.         Errcode = EBREAK;
  1947.         Int_caught = 0;
  1948.         return (1);
  1949.     }
  1950.     else if (Hup_caught)
  1951.     {
  1952.         Errcode = EHANGUP;
  1953.         Hup_caught = 0;
  1954.         return (1);
  1955.     }
  1956.     return (0);
  1957. }
  1958.  
  1959. /* int_hdlr --- handle an interrupt signal */
  1960.  
  1961. int_hdlr ()
  1962. {
  1963. #ifndef BSD4_2
  1964.     signal (SIGINT, int_hdlr);
  1965. #endif
  1966.     Int_caught = 1;
  1967. }
  1968.  
  1969. /* hup_hdlr --- handle a hangup signal */
  1970.  
  1971. hup_hdlr ()
  1972. {
  1973. #ifndef BSD4_2
  1974.     signal (SIGHUP, hup_hdlr);
  1975.     Hup_caught = 1;
  1976. #else
  1977.     /* do things different cause of 4.2 (sigh) */
  1978.     Hup_caught = 1;
  1979.     if (Reading)    /* doing tty i/o, and that is where hup came from */
  1980.         hangup ();
  1981. #endif
  1982. }
  1983.  
  1984. #ifdef BSD
  1985. /* stop_hdlr --- handle the berkeley stop/suspend signal */
  1986.  
  1987. int stop_hdlr ()
  1988. {
  1989.     clrscreen ();
  1990.     tflush ();
  1991.     ttynormal ();
  1992. #ifdef BSD4_2
  1993.     /* this handler remains in effect, use uncatchable signal */
  1994.     kill (getpid(), SIGSTOP);
  1995. #else
  1996.     /* action was reset to default when we caught it */
  1997.     kill (getpid(), SIGTSTP);
  1998. #endif
  1999.     /*
  2000.      * user does a "fg"
  2001.      */
  2002. #ifndef BSD4_2
  2003.     signal (SIGTSTP, stop_hdlr);    /* reset stop catching */
  2004. #endif
  2005.     ttyedit ();
  2006.     restore_screen ();
  2007. }
  2008. #endif
  2009.  
  2010. /* hangup --- dump contents of edit buffer if SIGHUP occurs */
  2011.  
  2012. hangup ()
  2013. {
  2014.     /* close terminal to avoid hanging on any accidental I/O: */
  2015.     close (0);
  2016.     close (1);
  2017.     close (2);
  2018.  
  2019.     signal (SIGHUP, SIG_IGN);
  2020.     signal (SIGINT, SIG_IGN);
  2021.     signal (SIGQUIT, SIG_IGN);
  2022.     Hup_caught = 0;
  2023.     Crypting = NO;        /* force buffer to be clear text */
  2024.     dowrit (1, Lastln, "se.hangup", NO, YES, NO);
  2025.     clrbuf ();
  2026.     exit (1);
  2027. }
  2028.  
  2029. /* mswait --- message waiting subroutine */
  2030.  
  2031. /* if the user wants to be notified, and the mail file is readable, */
  2032. /* and there is something in it, then he is given the message. */
  2033. /* the om command toggles Notify, controlling notification. */
  2034.  
  2035. #include <sys/types.h>
  2036. #include <sys/stat.h>
  2037.  
  2038. mswait ()
  2039. {
  2040.     int access ();
  2041.     struct stat buf;
  2042.     static char *mbox = NULL;
  2043.     static int first = YES;
  2044.     static unsigned long mtime = 0L;
  2045.  
  2046.     if (! Notify)
  2047.         return;
  2048.  
  2049.     if (first) 
  2050.     {
  2051.         first = NO;
  2052.         if ((mbox = getenv ("MAIL")) != NULL && access (mbox, 4) == 0)
  2053.         {
  2054.             if (stat (mbox, &buf) >= 0)
  2055.             {
  2056.                 mtime = buf.st_mtime;
  2057.                 if (buf.st_size > 0)
  2058.                     remark ("You have mail");
  2059.             }
  2060.         }
  2061.     }
  2062.     else if (mbox && stat (mbox, &buf) >= 0 && buf.st_mtime > mtime)
  2063.     {
  2064.         mtime = buf.st_mtime;
  2065.         remark ("You have new mail");
  2066.         twrite (1, "\007", 1);    /* Bell */
  2067.     }
  2068. }
  2069.  
  2070. /* printverboseerrormessage --- print verbose error message */
  2071.  
  2072. printverboseerrormessage ()
  2073. {
  2074.     switch (Errcode) {
  2075.     case EBACKWARD:
  2076.         remark ("Line numbers in backward order"); 
  2077.         break;
  2078.     case ENOPAT:
  2079.         remark ("No saved pattern -- sorry"); 
  2080.         break;
  2081.     case EBADPAT:
  2082.         remark ("Bad syntax in pattern"); 
  2083.         break;
  2084.     case EBADSTR:
  2085.         remark ("Bad syntax in string parameter"); 
  2086.         break;
  2087.     case EBADSUB:
  2088.         remark ("Bad syntax in substitution string"); 
  2089.         break;
  2090.     case ECANTREAD:
  2091.         remark ("File is not readable"); 
  2092.         break;
  2093.     case EEGARB:
  2094.         remark ("Garbage after your command"); 
  2095.         break;
  2096.     case EFILEN:
  2097.         remark ("Bad syntax in file name"); 
  2098.         break;
  2099.     case EBADTABS:
  2100.         remark ("Bad tabstop syntax"); 
  2101.         break;
  2102.     case EINSIDEOUT:
  2103.         remark ("Can't move a group into itself"); 
  2104.         break;
  2105.     case EKNOTFND:
  2106.         remark ("No line has that mark name"); 
  2107.         break;
  2108.     case ELINE1:
  2109.         remark (""); 
  2110.         break;
  2111.     case E2LONG:
  2112.         remark ("Resultant line too long to handle"); 
  2113.         break;
  2114.     case ENOERR:
  2115.         remark ("No error to report"); 
  2116.         break;
  2117.     case ENOLIMBO:
  2118.         remark ("No lines in limbo"); 
  2119.         break;
  2120.     case EODLSSGTR:
  2121.         remark ("Expected '<', '>', or nothing after 'od'"); 
  2122.         break;
  2123.     case EORANGE:
  2124.         remark ("Line number out of range"); 
  2125.         break;
  2126.     case EOWHAT:
  2127.         remark ("Can't recognize option"); 
  2128.         break;
  2129.     case EPNOTFND:
  2130.         remark ("No line contains that pattern"); 
  2131.         break;
  2132.     case ESTUPID:
  2133.         remark ("Buffer hasn't been saved"); 
  2134.         break;
  2135.     case EWHATZAT:
  2136.         remark ("No command recognized"); 
  2137.         break;
  2138.     case EBREAK:
  2139.         remark ("You interrupted me"); 
  2140.         break;
  2141.     case ELINE2:
  2142.         remark ("Last line number beyond end of file"); 
  2143.         break;
  2144.     case ECANTWRITE:
  2145.         remark ("File is not writeable"); 
  2146.         break;
  2147.     case ECANTINJECT:
  2148.         remark ("No room for any more lines!"); 
  2149.         break;
  2150.     case ENOMATCH:
  2151.         remark ("No match for pattern"); 
  2152.         break;
  2153.     case ENOFN:
  2154.         remark ("No saved filename"); 
  2155.         break;
  2156.     case EBADLIST:
  2157.         remark ("Bad syntax in character list"); 
  2158.         break;
  2159.     case ENOLIST:
  2160.         remark ("No saved character list -- sorry"); 
  2161.         break;
  2162.     case ENONSENSE:
  2163.         remark ("Unreasonable value"); 
  2164.         break;
  2165.     case ENOHELP:
  2166.         remark ("No help available"); 
  2167.         break;
  2168.     case EBADLNR:
  2169.         remark ("Line numbers not allowed"); 
  2170.         break;
  2171.     case EFEXISTS:
  2172.         remark ("File already exists"); 
  2173.         break;
  2174.     case EBADCOL:
  2175.         remark ("Improper column number specification"); 
  2176.         break;
  2177.     case ENOLANG:
  2178.         remark ("Unknown source language"); 
  2179.         break;
  2180.     case ETRUNC:
  2181.         remark ("Lines were truncated"); 
  2182.         break;
  2183.     case ENOSHELL:
  2184.         remark ("Type control-q to rebuild screen"); 
  2185.         break;
  2186.     case ECANTFORK:
  2187.         remark ("Can't fork --- get help!"); 
  2188.         break;
  2189.     case ENOSUB:
  2190.         remark ("No saved replacement --- sorry"); 
  2191.         break;
  2192.     case ENOCMD:
  2193.         remark ("No saved shell command --- sorry");
  2194.         break;
  2195.     default:
  2196.         remark ("?"); 
  2197.         break;
  2198.     }
  2199.     Errcode = ENOERR;
  2200. }
  2201.  
  2202. /* usage --- print usage diagnostic and die */
  2203.  
  2204. usage ()
  2205. {
  2206.     ttynormal ();
  2207.     fprintf (stderr, "Usage: se%s%s\n",
  2208. #ifdef HARD_TERMS
  2209.     " [ -t <terminal> ] ",
  2210. #else
  2211.     " ",
  2212. #endif
  2213.     "[ --acdfghiklmstuvwxyz ] [ file ... ]");
  2214.     exit (1);
  2215. }
  2216. SHAR_EOF
  2217. fi # end of overwriting check
  2218. echo shar: extracting "'makefile'" '(3680 characters)'
  2219. if test -f 'makefile'
  2220. then
  2221.     echo shar: will not over-write existing file "'makefile'"
  2222. else
  2223. cat << \SHAR_EOF > 'makefile'
  2224. # $Header: makefile,v 1.3 86/09/19 12:16:19 arnold Exp $
  2225. # $Log:    makefile,v $
  2226. # Revision 1.3  86/09/19  12:16:19  arnold
  2227. # Fixed to ignore return code from shell if statement.
  2228. # Revision 1.2  86/05/27  17:47:50  osadr
  2229. # Changes to support the Unix PC (no egrep, shared library), and
  2230. # to support making if . is not in the search path.
  2231. # Revision 1.1  86/05/06  13:39:18  osadr
  2232. # Initial revision
  2233. # makefile for the Georgia Tech Screen Editor, 'se'
  2234.  
  2235. HEADERS= ascii.h constdefs.h extern.h se.h
  2236.  
  2237. SRCS= docmd1.c docmd2.c edit.c main.c misc.c scratch.c screen.c term.c
  2238. OBJS= docmd1.o docmd2.o edit.o main.o misc.o scratch.o screen.o term.o
  2239.  
  2240. LIBRARIES= libchangetty/libchangetty.a pat/libpat.a
  2241.  
  2242. DOCS= makefile README
  2243. MANS= scriptse.1 se.1
  2244.  
  2245. CFLAGS= -O `cat flags`
  2246. LDFLAGS=
  2247.  
  2248. # On BSD systems, force make to use the right shell for commands
  2249. SHELL=/bin/sh
  2250.  
  2251. ###########################################################################
  2252. # Begin system dependant macro definitions
  2253.  
  2254. # PR is to print the files nicely.  Use pr -n if available, or else just pr
  2255. # I use a private utility called 'prt'
  2256. PR=pr
  2257.  
  2258. # NROFF is for nroffing.  we use the System V nroff. 
  2259. NROFF=/usr/5bin/nroff
  2260.  
  2261. # MANSEC is where to put the manual pages. Use 'l' for local, otherwise '1'.
  2262. MANSEC=l
  2263.  
  2264. # DESTBIN is where se and scriptse will go
  2265. DESTBIN= /usr/local/bin
  2266.  
  2267. # OWNER and GROUP are the owner and group respectively
  2268. OWNER= root
  2269. GROUP= sys
  2270.  
  2271. # INSTALL is the program to do the installation, use cp for real work
  2272. INSTALL= cp
  2273.  
  2274. # CHOWN changes the owner.
  2275. CHOWN= /etc/chown
  2276.  
  2277. # CHGRP changes the group.
  2278. CHGRP= chgrp
  2279.  
  2280. # CHMOD will change permissions.
  2281. CHMOD= chmod
  2282.  
  2283. ########
  2284. # other things to change:
  2285. #
  2286. # on non-BSD systems, change the 'lpr' below to 'lp'
  2287. ########
  2288.  
  2289. # Begin list of dependencies
  2290.  
  2291. all: se scriptse se.1
  2292.     @echo all done
  2293.  
  2294. se: $(OBJS) $(LIBRARIES)
  2295.     if grep DBSD flags > /dev/null || grep US5R2 flags > /dev/null; \
  2296.     then    echo -ltermlib > libs; \
  2297.     else    echo -lcurses > libs ; \
  2298.     fi
  2299.     -if [ -f /lib/shlib.ifile ] ; \
  2300.     then    ld /lib/crt0s.o /lib/shlib.ifile $(OBJS) $(LIBRARIES) -o $@ ; \
  2301.     else    $(CC) $(LDFLAGS) $(OBJS) $(LIBRARIES) `cat libs` -o $@ ; \
  2302.     fi
  2303.     rm libs
  2304.  
  2305. $(OBJS): $(HEADERS) flags
  2306.  
  2307. flags: where
  2308.     ./where > flags
  2309.  
  2310. libchangetty/libchangetty.a: libchangetty/changetty.c
  2311.     cd libchangetty; make
  2312.  
  2313. pat/libpat.a: pat/pat.c
  2314.     cd pat; make
  2315.  
  2316. scriptse: scriptse.c
  2317.     $(CC) -O scriptse.c -o scriptse
  2318.  
  2319. se.1: se.m4 flags
  2320.     (./m4munge $(CFLAGS) ; cat se.m4) | m4 | sed '/^$$/d' > se.1
  2321.  
  2322. install: all $(MANS)
  2323.     $(INSTALL) se $(DESTBIN)
  2324.     $(CHOWN) $(OWNER) $(DESTBIN)/se
  2325.     $(CHGRP) $(GROUP) $(DESTBIN)/se
  2326.     $(CHMOD) 711 $(DESTBIN)/se 
  2327.     $(INSTALL) scriptse $(DESTBIN)
  2328.     $(CHOWN) $(OWNER) $(DESTBIN)/scriptse
  2329.     $(CHGRP) $(GROUP) $(DESTBIN)/scriptse
  2330.     $(CHMOD) 711 $(DESTBIN)/scriptse 
  2331.     $(INSTALL) se.1 /usr/man/man$(MANSEC)/se.$(MANSEC)
  2332.     $(CHOWN) $(OWNER) /usr/man/man$(MANSEC)/se.$(MANSEC)
  2333.     $(CHGRP) $(GROUP) /usr/man/man$(MANSEC)/se.$(MANSEC)
  2334.     $(CHMOD) 644 /usr/man/man$(MANSEC)/se.$(MANSEC)
  2335.     $(INSTALL) scriptse.1 /usr/man/man$(MANSEC)/scriptse.$(MANSEC)
  2336.     $(CHOWN) $(OWNER) /usr/man/man$(MANSEC)/scriptse.$(MANSEC)
  2337.     $(CHGRP) $(GROUP) /usr/man/man$(MANSEC)/scriptse.$(MANSEC)
  2338.     $(CHMOD) 644 /usr/man/man$(MANSEC)/scriptse.$(MANSEC)
  2339.     cd se_h; make install
  2340.     
  2341. print:
  2342.     $(PR) $(HEADERS) $(SRCS) $(DOCS) $(MANS) | lpr
  2343.  
  2344. printman: $(MANS)
  2345.     $(NROFF) -man $(MANS) | col | lpr
  2346.  
  2347. print2:    $(HEADERS) $(SRCS) $(DOCS) $(MANS)
  2348.     $(PR) $? | lpr
  2349.  
  2350. printall: printman print
  2351.     cd pat; make print
  2352.     cd libchangetty; make print
  2353.     cd se_h; make print
  2354.  
  2355. clean:
  2356.     rm -f *.o print2
  2357.     cd pat; make clean
  2358.     cd libchangetty; make clean
  2359.  
  2360. clobber: clean
  2361.     rm -f se scriptse flags se.1
  2362.     cd pat; make clobber
  2363.     cd libchangetty; make clobber
  2364.     cd se_h; make clobber
  2365. SHAR_EOF
  2366. fi # end of overwriting check
  2367. echo shar: extracting "'misc.c'" '(3315 characters)'
  2368. if test -f 'misc.c'
  2369. then
  2370.     echo shar: will not over-write existing file "'misc.c'"
  2371. else
  2372. cat << \SHAR_EOF > 'misc.c'
  2373. #ifndef lint
  2374. static char RCSid[] = "$Header: misc.c,v 1.1 86/05/06 13:37:51 osadr Exp $";
  2375. #endif
  2376.  
  2377. /*
  2378.  * $Log:    misc.c,v $
  2379.  * Revision 1.1  86/05/06  13:37:51  osadr
  2380.  * Initial revision
  2381.  * 
  2382.  * 
  2383.  */
  2384.  
  2385. /*
  2386. ** misc.c
  2387. **
  2388. ** lots of miscellanious routines for the screen editor.
  2389. */
  2390.  
  2391. #include "se.h"
  2392. #include "extern.h"
  2393.  
  2394. /* cprow --- copy from one row to another for append */
  2395.  
  2396. cprow (from, to)
  2397. register int from, to;
  2398. {
  2399.     register int col;
  2400.  
  2401.     for (col = 0; col < Ncols; col++)
  2402.         load (Screen_image[from][col], to, col);
  2403. }
  2404.  
  2405. /* index --- return position of character in string */
  2406.  
  2407. int index (str, c)
  2408. register char str[], c;
  2409. {
  2410.     register int i;
  2411.  
  2412.     for (i = 0; str[i] != EOS; i++)
  2413.         if (str[i] == c)
  2414.             return (i);
  2415.     return (-1);
  2416. }
  2417.  
  2418. /* strbsr --- binary search stab for an entry equal to str */
  2419.  
  2420. int strbsr (stab, tsize, esize, str)
  2421. char *stab, str[];
  2422. int tsize, esize;
  2423. {
  2424.     /* stab should have been declared like this:
  2425.  
  2426.     static struct {
  2427.         char *s;
  2428.         ...
  2429.         } stab[] = {
  2430.         "string1",      ...
  2431.         "string2",      ...
  2432.         ...             ...
  2433.         };
  2434.  
  2435.     The call to strbsr should look like this:
  2436.  
  2437.     i = strbsr (stab, sizeof (stab), sizeof (stab[0]), str);
  2438.     */
  2439.  
  2440.     register int i, j, k, x;
  2441.     int strcmp ();
  2442.  
  2443.     i = 0;
  2444.     j = tsize / esize - 1;
  2445.     do {
  2446.         k = (i + j) / 2;
  2447.         if ((x = strcmp (str, *(char **)(stab + esize * k))) < 0)
  2448.             j = k - 1;              /* GREATER */
  2449.         else if (x == 0)
  2450.             return (k);             /* EQUAL */
  2451.         else
  2452.             i = k + 1;              /* LESS */
  2453.     } while (i <= j);
  2454.  
  2455.     return (EOF);
  2456. }
  2457.  
  2458. /* strmap --- map a string to upper/lower case */
  2459.  
  2460. int strmap (str, ul)
  2461. register char str[];
  2462. int ul;
  2463. {
  2464.     register int i;
  2465.  
  2466.     if (isupper (ul))
  2467.         for (i = 0; str[i] != '0'; i++)
  2468.             str[i] = islower (str[i]) ? toupper (str[i]) : str[i];
  2469.     else
  2470.         for (i = 0; str[i] == EOS; i++)
  2471.             str[i] = isupper (str[i]) ? tolower (str[i]) : str[i];
  2472.     return (i);
  2473. }
  2474.  
  2475.  
  2476. /* xindex --- invert condition returned by index */
  2477.  
  2478. int xindex (array, c, allbut, lastto)
  2479. char array[], c;
  2480. int allbut, lastto;
  2481. {
  2482.     int index ();
  2483.  
  2484.     if (c == EOS)
  2485.         return (-1);
  2486.     if (allbut == NO)
  2487.         return (index (array, c));
  2488.     if (index (array, c) > -1)
  2489.         return (-1);
  2490.     return (lastto + 1);
  2491. }
  2492.  
  2493.  
  2494. /* ctoi --- convert decimal string to a single precision integer */
  2495.  
  2496. int ctoi (str, i)
  2497. register char str[];
  2498. register int *i;
  2499. {
  2500.     register int ret;
  2501.  
  2502.     SKIPBL (str, *i);
  2503.     for (ret = 0; isdigit (str[*i]); (*i)++)
  2504.         ret = ret * 10 + (str[*i] - '0');
  2505.     return (ret);
  2506. }
  2507.  
  2508.  
  2509. /* move_ --- move l bytes from here to there */
  2510.  
  2511. move_ (here, there, l)
  2512. register char *here, *there;
  2513. register int l;
  2514. {
  2515.     while (l--)
  2516.         *there++ = *here++;
  2517. }
  2518.  
  2519.  
  2520. /* twrite --- stuff characters into the terminal output buffer */
  2521.  
  2522. twrite (fd, buf, len)
  2523. register int fd, len;
  2524. register char *buf;
  2525. {
  2526.  
  2527.     if ((Tobp - Tobuf) + 1 + len > MAXTOBUF)
  2528.         tflush ();
  2529.  
  2530.     if (fd != 1 || len > MAXTOBUF)
  2531.     {
  2532.         write (fd, buf, len);
  2533.         return;
  2534.     }
  2535.  
  2536.     while (len--)
  2537.         *++Tobp = *buf++;
  2538. }
  2539.  
  2540.  
  2541. /* tflush --- clear out the terminal output buffer */
  2542.  
  2543. tflush ()
  2544. {
  2545.     write (1, Tobuf, (int)(Tobp - Tobuf + 1));
  2546.     Tobp = Tobuf - 1;
  2547. }
  2548.  
  2549.  
  2550.  
  2551. /* basename -- return last portion of a pathname */
  2552.  
  2553. char *basename (str)
  2554. register char *str;
  2555. {
  2556.     register char *cp;
  2557. #ifdef USG
  2558. #define rindex    strrchr
  2559. #endif
  2560.     char *rindex ();
  2561.  
  2562.     if ((cp = rindex(str, '/')) == NULL)
  2563.         return (str);    /* no '/' found, return whole name */
  2564.     else
  2565.         return (++cp);    /* skip over slash to name after it */
  2566. }
  2567. SHAR_EOF
  2568. fi # end of overwriting check
  2569. #    End of shell archive
  2570. exit 0
  2571.  
  2572.